import { ref, readonly, onBeforeUnmount } from 'vue'
import { Direction, Status } from '../constants'
import { useDirection, defaultDirection } from './useDirection'
import Board from './Board'

interface Props {
  width: number
  height: number
  fps: number
  withWalls: boolean
}

const useSnakeGame = ({ width, height, withWalls, fps }: Props) => {
  let handle: number | null = null
  let board = new Board(width, height, withWalls)
  const updateInterval = 1000 / fps
  const status = ref(Status.INITIALIZED)
  const boardArray = ref(board.serialize())
  const score = ref(board.score)
  const [direction, setDirection] = useDirection()

  const updateBoard = () => {
    status.value = board.nextTick(direction.value)
    switch (status.value) {
      case Status.COLLIDED:
        handle !== null && clearInterval(handle)
        return
      case Status.ATE:
      case Status.MOVED:
        score.value = board.score
        boardArray.value = board.serialize()
        break
      default:
    }
  }
  const start = () => {
    handle = setInterval(updateBoard, updateInterval)
    status.value = Status.MOVED
  }
  const restart = () => {
    board = new Board(width, height, withWalls)
    boardArray.value = board.serialize()
    setDirection(defaultDirection)
    start()
  }
  const pause = () => {
    handle !== null && clearInterval(handle)
  }
  const changeDirection = (newDirection: Direction) => {
    const allowed = board.allowedMovementDirections()
    if (allowed.includes(newDirection)) setDirection(newDirection)
  }

  onBeforeUnmount(() => handle && clearInterval(handle))

  return {
    start,
    restart,
    pause,
    changeDirection,
    status: readonly(status),
    boardArray: readonly(boardArray),
    score: readonly(score)
  }
}

export default useSnakeGame
